package com.hsqyz.common.utils.start;

import cn.hutool.core.net.NetUtil;
import cn.hutool.system.OsInfo;
import cn.hutool.system.SystemUtil;
import com.hsqyz.common.utils.ip.AddressUtils;
import com.hsqyz.common.utils.spring.SpringUtils;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.context.metrics.buffering.BufferingApplicationStartup;
import org.springframework.context.ConfigurableApplicationContext;

import java.net.InetAddress;

import static cn.hutool.http.HttpUtil.get;

/**
 * 启动工具
 *
 * @author lcz
 */
public class StartUtil {

    /**
     * 启动
     *
     * @param primarySource 主类
     * @param args          参数
     */
    public static ConfigurableApplicationContext start(Class<?> primarySource, String... args) {
        String applicationName = SpringUtils.getApplicationName();
        //----------------------------- 获取上下文-------------------------------
        // 创建Spring Boot应用实例
        SpringApplication application = new SpringApplication(primarySource);
        // 设置应用启动策略，使用BufferingApplicationStartup来缓冲启动过程中的信息
        application.setApplicationStartup(new BufferingApplicationStartup(2048));
        // 启动应用
        ConfigurableApplicationContext applicationContext = application.run(args);
        //--------------------------获取 公网 IP 地址----------------------------
        String publicIp = get("https://ifconfig.me");
        //----------------------------获取环境变量-------------------------------
        String activeProfile = SpringUtils.getActiveProfile();
        String port = SpringUtils.getProperty("server.port");
        InetAddress localhost = NetUtil.getLocalhost();
        String hostAddress = localhost.getHostAddress();
        String cityAddress = AddressUtils.getRealAddressByIP(publicIp);
        String contextPath = SpringUtils.getProperty("server.servlet.context-path");
        String datasourceMasterUrl = SpringUtils.getProperty("spring.datasource.dynamic.datasource.master.url");
        String redisUrl = SpringUtils.getProperty("spring.redis.host");
        OsInfo osInfo = SystemUtil.getOsInfo();
        Runtime runtime = Runtime.getRuntime();

        //----------------------------获取 JDK 信息-----------------------------
        String javaVersion = System.getProperty("java.version");
        String javaVmName = System.getProperty("java.vm.name");

        //--------------------------获取 JVM 内存信息----------------------------
        // 获取总内存
        long totalMemory = runtime.totalMemory();
        // 获取空闲内存
        long freeMemory = runtime.freeMemory();
        // 计算已使用的内存
        long usedMemory = totalMemory - freeMemory;
        // 获取最大可用内存
        long maxMemory = runtime.maxMemory();

        //-----------------------------输出信息----------------------------------
        System.out.println("==================================================");
        // 输出启动成功信息
        System.err.println(applicationName + "启动成功！");
        // 输出内存信息
        System.err.println("JVM总内存: " + formatBytes(totalMemory));
        System.err.println("JVM空闲内存: " + formatBytes(freeMemory));
        System.err.println("JVM已使用内存: " + formatBytes(usedMemory));
        System.err.println("JVM最大可用内存: " + formatBytes(maxMemory));
        // 输出 JDK 信息
        System.err.println("JDK版本: " + javaVersion);
        System.err.println("JDK虚拟机名称: " + javaVmName);
        // 输出运行环境信息
        System.err.println("运行系统: " + osInfo.getName());
        System.err.println("项目环境：" + activeProfile);
        System.err.println("项目端口：" + port);
        System.err.println("接口前缀：" + contextPath);
        System.err.println("Redis地址：" + redisUrl);
        System.err.println("数据库地址：" + datasourceMasterUrl);
        System.err.println("公网 IP：" + publicIp);
        System.err.println("内网 IP：" + hostAddress);
        System.err.println("真实地址：" + cityAddress);
        System.err.println("接口文档: http://127.0.0.1:" + port + contextPath + "doc.html");
        System.err.println("对接地址: http://" + hostAddress + ":" + port + contextPath);
        System.out.println("==================================================");
        return applicationContext;
    }

    /**
     * 将字节数转换为人类可读的格式
     *
     * @param bytes 字节数
     * @return 人类可读的格式
     */
    private static String formatBytes(long bytes) {
        // 判断是否大于等于1GB
        if (bytes >= 1024 * 1024 * 1024) {
            // 返回格式化后的结果
            return String.format("%.2f GB", bytes / (1024.0 * 1024 * 1024));
        } else if (bytes >= 1024 * 1024) { // 判断是否大于等于1MB
            // 返回格式化后的结果
            return String.format("%.2f MB", bytes / (1024.0 * 1024));
        } else if (bytes >= 1024) { // 判断是否大于等于1KB
            // 返回格式化后的结果
            return String.format("%.2f KB", bytes / 1024.0);
        } else { // 小于1KB，直接返回字节数
            // 返回字节数
            return bytes + " B";
        }
    }


}
